<?php
namespace App\ModelStatistic;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Input;


class RetainNewPlayerHour extends  Model{

	protected $table='retain_new_hour';
    protected $_db_select = '';
    const DB_FIELDS = "area,retain_time,retain_num,day1,day2,day3,day4,day5,day6,day7,day14,day30,cache";
    const STATISTIC_DAY = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30];
    const RETAIN_STEP = 3600;
    const RETAIN_STEP_DAY = 86400;

    // const UPDATED_AT = null;
    // const CREATED_AT = null;
	public function paginate()
    {
        
        
    	$perPage = Request::get('per_page', 100);

        $page = Request::get('page', 1);
        
        $start = ($page-1)*$perPage;

        $qdCond = StatisticCommon::remainChartDate(Request::get('retain_time'));
        \Log::debug(__METHOD__, [$this->selectdb(),$qdCond,\Config::get("database.connections.remote_bgsi")]);
        $tableAccount = 'retain_new_hour';
        //$offset = ($page - 1) * $perPage;
        //$limit = $perPage;
        if (0 != ($qdCond['code'])){
            admin_toastr($qdCond['msg'] . $qdCond['code'],'error');
            return $paginator = new LengthAwarePaginator([], 0, $perPage);
        }
        //$sql = "SELECT * FROM tb_new_user_login ORDER BY id DESC limit $offset, $limit";
        $rw = \DB::connection($this->selectdb())->table($tableAccount);
        $rw = $rw->where('area', intval(Request::get("area")));
        // 自定义时间查询
        if (isset($qdCond['start'])) {
            //$rw->where('reg_time', '>=', "0");
            $rw->whereRaw("retain_time >= '{$qdCond['start']}'");
        }

        if (isset($qdCond['end'])) {
            //$rw->where('reg_time', '<=', "{$qdRond['end']}");
            $rw->whereRaw("retain_time <= '{$qdCond['end']}'");
        }
        //$result = \DB::connection($this->selectdb())->select($sql);

        $rw->orderBy('retain_time', 'ASC');
        $rw->skip($page* $perPage - $perPage)->take($perPage);
        $result = $rw->get();

        $result = $result->toArray();

        \Log::debug(__METHOD__,['generate start',  $rw->toSql(), $rw->getBindings()]);
        self::Generate(intval(Request::get("area")), $qdCond['start'], $qdCond['end'], $result);
        \Log::debug(__METHOD__, ['generate end', []]);

        $total = $rw->count();

        $list = static::hydrate($result);

        $paginator = new LengthAwarePaginator($list, $total, $perPage);

        $paginator->setPath(url()->current());

        return $paginator;
    }

    public static function with($relations)
    {
        return new static;
    }


    public function selectdb(){
        if ($this->_db_select) {
            return $this->_db_select;
        }
        //\App\Models\Area::RemoteBgsiSelectByArea(Input::get('area'));
        $this->_db_select = 'mysql_statistic';
        return $this->_db_select;
    }

    public function getConnectionName(){
        
        return $this->selectdb();
    }

    public function clearData() {
        $qdCond = StatisticCommon::remainChartDate(Request::get('retain_time'));
        
        $rw = \DB::connection($this->selectdb())->table($this->table);
        $rw = $rw->where('area', intval(Request::get("area")));
        // 自定义时间查询
        if (isset($qdCond['start'])) {
            //$rw->where('reg_time', '>=', "0");
            $rw->whereRaw("retain_time >= '{$qdCond['start']}'");
        }

        if (isset($qdCond['end'])) {
            //$rw->where('reg_time', '<=', "{$qdRond['end']}");
            $rw->whereRaw("retain_time <= '{$qdCond['end']}'");
        }
        $rw->delete();
    }

    public function where()
    {
        //\Log::debug(__METHOD__, [\Config::get("database.connections.remote_bgsi")]);
        $this->query = parent::where(...func_get_args());
        return $this;
    }



    public function AssignData($one, $data)
    {
        foreach($data as $fld => $value)
        {
            $one->$fld = $value;
        }

        if (!empty($data['cache'])) {
            $one->cache = $data['cache'];
        }
    }

    public static function SaveByArray($data)
    {
        if (!$data["retain_time"]){
            return ;
        }
        $one = self::find($data["id"]) ?:new self;
        $one->AssignData($one, $data);
        if (!is_string($data['cache'])){
            $one->cache = json_encode($one->cache);
        }
        // \Log::debug(__METHOD__, [$data]);
        $one->save();
    }

    public static function Generate($area, $start, $end, $data = [])
    {
        
        if (!$end || $end > time()){
            $end = time();
        }
        if (intval($start) !== $start) {
            $start = strtotime($start);
        }
        if (intval($end) !== $end) {
            $end = strtotime($end);
        }
        // 开始时间 和 区服未选择的话，直接只做查询不做统计
        if (!$start || !$area || $start > $end){
            \Log::debug(__METHOD__, ["mabay empty start:" . $start, "mabay empty area:".$area, "mabay start > end:{$end}", "so cant generate statistic data"]);
            return;
        }
        \Log::debug(__METHOD__, [$area, $start, $end]);
        $list = [];
        \App\Models\Area::RemoteBgsiSelectByArea($area);
        foreach($data as $item){
            $item = (array)$item;
            $list[$item['retain_time']] = $item;
            $list[$item['retain_time']]['cache'] = $item['cache'] ? json_decode($item['cache'], true) : [];
        }

        $start = strtotime(date("Y-m-d", $start));
        $end = strtotime(date("Y-m-d", $end));
        $end_count = ($end - $start)/self::RETAIN_STEP;
        // 最多做100条统计
        ($end_count > 100) && $end_count = 100;
        $cur_int = strtotime(date("Y-m-d"));

        $player_retain_arr = [];
        for ($step = 0; $step<= $end_count; $step++){
            $tmp_int = $start + $step * self::RETAIN_STEP;
            $obj = null;
            if (empty($list[$tmp_int])){
                //$list[$tmp_int] = new self();
                $list[$tmp_int]['retain_time'] = $tmp_int;
                $list[$tmp_int]['area'] = $area;
            }
            
            $obj = $list[$tmp_int];
            $changed = false;
            !$obj['area'] && $obj['area'] = $area;
            // 表示是当天统计的  再次看的时候要重新查 注册数
            if ($obj['retain_num'] <= 0){
                $obj['retain_num'] = count(self::GetPlayersByRetain($player_retain_arr, $area, $obj['retain_time'], self::RETAIN_STEP));
                $changed = true;
            }
            
            if ( date("Y-m-d", $tmp_int) == date("Y-m-d", $cur_int)){
                $obj['retain_num'] *= -1;
            }
            $tttt = date('Y-m-d',$tmp_int);
            \Log::debug(__METHOD__, ["STEP[{$tttt}]", $obj['retain_num'], array_keys($player_retain_arr)]);
            if ($obj['retain_num'] == 0){
                continue;
            }
           
            foreach(self::STATISTIC_DAY as $day){
                
                // 切割每个属性 是统计属性的 去处理
                $obj_attr = 'day'.$day;

                // 统计日期大于当前时间，直接过跳过循环
                $zero_int = strtotime(date("Y-m-d", $tmp_int));
                $cur_day_tmp_int = $zero_int + self::RETAIN_STEP_DAY * $day;
                if ($cur_day_tmp_int > $cur_int) {
                    break;
                }

                // 大于0值 表示 正确的且不会再改变 不需要再查询
                // 等于0值 标志位是 已查过， 则不用去再查询
                if ($obj[$obj_attr] > 0 || $obj['cache'][$obj_attr] == 1){
                    continue;
                }
               
                $equal_cur_op = 1;// 表示与查询日期相等， 如果是1 表示不相等 -1 表示相等 是临时数据
                if ($cur_day_tmp_int == $cur_int) {
                    $equal_cur_op = -1;
                }

                $login_num = self::GetLoginNum($area, $cur_day_tmp_int, self::GetPlayersByRetain($player_retain_arr, $area, $obj['retain_time'], self::RETAIN_STEP));
                $obj[$obj_attr] = $login_num * $equal_cur_op;
                
                // 当未有更改的时候不做保存 这里有问题当留存人数就是0的 每次都需要查询会很慢
                \Log::debug(__METHOD__, ["STEP FIELD LOOP", date('Y-m-d', $cur_day_tmp_int), ($login_num)]);
                $changed = true;
                
                // 0值 保存 查询状态 下次不用查
                ($obj[$obj_attr] == 0 && $equal_cur_op != -1)  && $obj['cache'][$obj_attr] = 1;
            }
            if ($changed) {
    
                self::SaveByArray($obj);
            }
        }
    }

    // 获取留存比较日的 注册用户
    public static function GetPlayersByRetain(&$p_arr, $area, $retain_time, $dur_time = 86400)
    {
        $start = date("Y-m-d H:i:s", $retain_time);
        $end = date("Y-m-d H:i:s", $retain_time + $dur_time);

        if (!empty($p_arr[$retain_time])){
            return $p_arr[$retain_time];
        }

        $data = \DB::connection('remote_bgsi')->table('user_login')->select('player_id')->whereBetween('reg_time',[$start, $end])->groupBy("player_id");
        
        $data = $data->get();
        
        $player_ids_item = [];
        foreach($data as $obj){
            $player_ids_item[] = $obj->player_id;
        }
        $p_arr[$retain_time] = $player_ids_item;
        \Log::debug(__METHOD__, ['start', $start, $end, count($p_arr[$retain_time]) ]);
        return $player_ids_item;
    }

    public static function GetLoginNum($area, $login_time, $player_ids)
    {
        
        if (!$area || !$login_time || empty($player_ids)){
            return 0;
        }
       
        $start = date("Y-m-d 00:00:00", $login_time);
        $end = date("Y-m-d 23:59:59", $login_time);
        // $rw = \DB::connection('remote_bgsi')->table('user_login')->select(\DB::raw('count(*) as count_row'))->whereIn('player_id', $player_ids)->whereBetween('log_time',[$start, $end])->groupBy('player_id');
        //\Log::debug(__METHOD__, ['get login num BEGIN', $start, $end]);
        // $rtn = $rw->first();
        //\DB::connection('remote_bgsi')->enableQueryLog();
        $rw = \DB::connection('remote_bgsi')->table('user_login')->whereBetween('log_time',[$start, $end])->whereIn('player_id', $player_ids)->groupBy('player_id')->get();
        \Log::debug(__METHOD__, ['get login num BEGIN', count($player_ids), $start, $end]);
        $rtn = $rw->count();
        \Log::debug(__METHOD__, ['get login num END', ($rtn), ]);
        
        return ($rtn) ?: 0;
    }

}
